/****************************************************************************
 *	 $Id:: gpio.c 4068 2010-07-30 02:25:13Z usb00423												$
 *	 Project: NXP LPC11xx GPIO example
 *
 *	 Description:
 *		 This file contains GPIO code example which include GPIO 
 *		 initialization, GPIO interrupt handler, and related APIs for 
 *		 GPIO access.
 *
 ****************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
****************************************************************************/
#include "LPC11xx.h"			/* LPC11xx Peripheral Registers */
#include "../DaisyLink/DaisyLink.h"
#include "gpio.h"
#include "../Common/type.h"
#include "../Main/DL40.h"

/*****************************************************************************
** Function name:		PIOINT0_IRQHandler
**
** Descriptions:		Use one GPIO pin(port0 pin1) as interrupt source
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void PIOINT0_IRQHandler(void)
{
	int i;
	for (i = 0; i < 12; i++)
	{		
		if (GPIOIntStatus(PORT0, i))
		{		
			int index = i;			
			
			TPinConfig *pin = &g_pins[index];
			if (pin->InterruptFlag 
				&& (pin->Glitch100usTicks == 0 
						|| HAL_GetTicks100us() - pin->LastIntTime >= pin->Glitch100usTicks)) 
			{
				pin->LastIntTime = HAL_GetTicks100us();
				g_pinCounters[index].Count++;
				Reg.InterruptActive = 1;
			}
			else if (!g_pins[index].InterruptFlag)
			{
				g_pinCounters[index].Count++;
			}
			
			GPIOIntClear(PORT0, i);
		}
	}
}

/*****************************************************************************
** Function name:		PIOINT1_IRQHandler
**
** Descriptions:		Use one GPIO pin(port1 pin1) as interrupt source
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void PIOINT1_IRQHandler(void)
{
	int i;
	for (i = 0; i < 12; i++)
	{
		if (GPIOIntStatus(PORT1, i))
		{
			int index = 12 + i;
			
			TPinConfig *pin = &g_pins[index];
			if (pin->InterruptFlag 
				&& (pin->Glitch100usTicks == 0 
						|| HAL_GetTicks100us() - pin->LastIntTime >= pin->Glitch100usTicks)) 
			{
				pin->LastIntTime = HAL_GetTicks100us();
				g_pinCounters[index].Count++;
				Reg.InterruptActive = 1;
			}
			else if (!g_pins[index].InterruptFlag)
			{
				g_pinCounters[index].Count++;
			}
			
			GPIOIntClear(PORT1, i);
		}
	}
}

/*****************************************************************************
** Function name:		PIOINT2_IRQHandler
**
** Descriptions:		Use one GPIO pin(port2 pin1) as interrupt source
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void PIOINT2_IRQHandler(void)
{
	int i;
	for (i = 0; i < 12; i++)
	{
		if (GPIOIntStatus(PORT2, i))
		{
			int index = 24 + i;
			
			TPinConfig *pin = &g_pins[index];
			if (pin->InterruptFlag 
				&& (pin->Glitch100usTicks == 0 
						|| HAL_GetTicks100us() - pin->LastIntTime >= pin->Glitch100usTicks)) 
			{
				pin->LastIntTime = HAL_GetTicks100us();
				g_pinCounters[index].Count++;
				Reg.InterruptActive = 1;
			}
			else if (!g_pins[index].InterruptFlag)
			{
				g_pinCounters[index].Count++;
			}
			
			GPIOIntClear(PORT2, i);
		}
	}
}

/*****************************************************************************
** Function name:		PIOINT3_IRQHandler
**
** Descriptions:		Use one GPIO pin(port3 pin1) as interrupt source
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void PIOINT3_IRQHandler(void)
{
	int i;
	for (i = 0; i < 6; i++)
	{
		if (GPIOIntStatus(PORT3, i))
		{
			int index = 36 + i;
			
			TPinConfig *pin = &g_pins[index];
			if (pin->InterruptFlag 
				&& (pin->Glitch100usTicks == 0 
						|| ((UINT32)HAL_GetTicks100us() - pin->LastIntTime) >= pin->Glitch100usTicks)) 
			{
				pin->LastIntTime = HAL_GetTicks100us();
				g_pinCounters[index].Count++;
				Reg.InterruptActive = 1;
			}
			else if (!g_pins[index].InterruptFlag)
			{
				g_pinCounters[index].Count++;
			}
			
			GPIOIntClear(PORT3, i);
		}
	}
}

/*****************************************************************************
** Function name:		GPIOInit
**
** Descriptions:		Initialize GPIO, install the
**						GPIO interrupt handler
**
** parameters:			None
** Returned value:		true or false, return false if the VIC table
**						is full and GPIO interrupt handler can be
**						installed.
** 
*****************************************************************************/
void GPIOInit( void )
{
	/* Enable AHB clock to the GPIO domain. */
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

#ifdef __JTAG_DISABLED	
	LPC_IOCON->R_PIO1_1	&= ~0x07;
	LPC_IOCON->R_PIO1_1	|= 0x01;
#endif
	LPC_IOCON->R_PIO1_2	&= ~0x07;
	LPC_IOCON->R_PIO1_2	|= 0x01;

	/* Set up NVIC when I/O pins are configured as external interrupts. */
	NVIC_EnableIRQ(EINT0_IRQn);
	NVIC_EnableIRQ(EINT1_IRQn);
	NVIC_EnableIRQ(EINT2_IRQn);
	NVIC_EnableIRQ(EINT3_IRQn);
	return;
}

volatile uint32_t *IOCON_PIO[] = {
	&LPC_IOCON->RESET_PIO0_0,
	&LPC_IOCON->PIO0_1,
	&LPC_IOCON->PIO0_2,
	&LPC_IOCON->PIO0_3,
	&LPC_IOCON->PIO0_4,
	&LPC_IOCON->PIO0_5,
	&LPC_IOCON->PIO0_6,
	&LPC_IOCON->PIO0_7,
	&LPC_IOCON->PIO0_8,
	&LPC_IOCON->PIO0_9,
	&LPC_IOCON->SWCLK_PIO0_10,
	&LPC_IOCON->R_PIO0_11,
	&LPC_IOCON->R_PIO1_0,
	&LPC_IOCON->R_PIO1_1,
	&LPC_IOCON->R_PIO1_2,
	&LPC_IOCON->SWDIO_PIO1_3,
	&LPC_IOCON->PIO1_4,
	&LPC_IOCON->PIO1_5,
	&LPC_IOCON->PIO1_6,
	&LPC_IOCON->PIO1_7,
	&LPC_IOCON->PIO1_8,
	&LPC_IOCON->PIO1_9,
	&LPC_IOCON->PIO1_10,
	&LPC_IOCON->PIO1_11,
	&LPC_IOCON->PIO2_0,
	&LPC_IOCON->PIO2_1,
	&LPC_IOCON->PIO2_2,
	&LPC_IOCON->PIO2_3,
	&LPC_IOCON->PIO2_4,
	&LPC_IOCON->PIO2_5,
	&LPC_IOCON->PIO2_6,
	&LPC_IOCON->PIO2_7,
	&LPC_IOCON->PIO2_8,
	&LPC_IOCON->PIO2_9,
	&LPC_IOCON->PIO2_10,
	&LPC_IOCON->PIO2_11,
	&LPC_IOCON->PIO3_0,
	&LPC_IOCON->PIO3_1,
	&LPC_IOCON->PIO3_2,
	&LPC_IOCON->PIO3_3,
	&LPC_IOCON->PIO3_4,
	&LPC_IOCON->PIO3_5};
	
/*****************************************************************************
** Function name:		GPIOSetInterrupt
**
** Descriptions:		Set resitor mode for the pin
**									0 - None
**									1 - Pull-down									
**									2 - Pull-up									
**									3 - Repeater
**
** parameters:			port num, bit position, mode
** Returned value:		None
** 
*****************************************************************************/
void GPIOSetResistorMode(uint32_t portNum, uint32_t bitPosi, uint32_t mode)
{
	volatile uint32_t *pio = IOCON_PIO[(portNum * 12) + bitPosi];
	*pio = ((*pio & ~0x18) | (mode << 3));
}

/*****************************************************************************
** Function name:		GPIOSetInterrupt
**
** Descriptions:		Set interrupt sense, event, etc.
**						edge or level, 0 is edge, 1 is level
**						single or double edge, 0 is single, 1 is double 
**						active high or low, etc.
**
** parameters:			port num, bit position, sense, single/doube, polarity
** Returned value:		None
** 
*****************************************************************************/
void GPIOSetInterrupt( uint32_t portNum, uint32_t bitPosi, uint32_t sense,
			uint32_t single, uint32_t event )
{
	switch ( portNum )
	{
	case PORT0:
		if ( sense == 0 )
		{
			LPC_GPIO0->IS &= ~(0x1<<bitPosi);
			/* single or double only applies when sense is 0(edge trigger). */
			if ( single == 0 )
				LPC_GPIO0->IBE &= ~(0x1<<bitPosi);
			else
				LPC_GPIO0->IBE |= (0x1<<bitPosi);
		}
		else
			LPC_GPIO0->IS |= (0x1<<bitPosi);
		
		if ( event == 0 )
			LPC_GPIO0->IEV &= ~(0x1<<bitPosi);
		else
			LPC_GPIO0->IEV |= (0x1<<bitPosi);
	break;
 	case PORT1:
		if ( sense == 0 )
		{
			LPC_GPIO1->IS &= ~(0x1<<bitPosi);
			/* single or double only applies when sense is 0(edge trigger). */
			if ( single == 0 )
				LPC_GPIO1->IBE &= ~(0x1<<bitPosi);
			else
				LPC_GPIO1->IBE |= (0x1<<bitPosi);
		}
		else
			LPC_GPIO1->IS |= (0x1<<bitPosi);
		
		if ( event == 0 )
			LPC_GPIO1->IEV &= ~(0x1<<bitPosi);
		else
			LPC_GPIO1->IEV |= (0x1<<bitPosi);	
	break;
	case PORT2:
		if ( sense == 0 )
		{
			LPC_GPIO2->IS &= ~(0x1<<bitPosi);
			/* single or double only applies when sense is 0(edge trigger). */
			if ( single == 0 )
				LPC_GPIO2->IBE &= ~(0x1<<bitPosi);
			else
				LPC_GPIO2->IBE |= (0x1<<bitPosi);
		}
		else
			LPC_GPIO2->IS |= (0x1<<bitPosi);

		if ( event == 0 )
			LPC_GPIO2->IEV &= ~(0x1<<bitPosi);
		else
			LPC_GPIO2->IEV |= (0x1<<bitPosi);	
	break;
	case PORT3:
		if ( sense == 0 )
		{
			LPC_GPIO3->IS &= ~(0x1<<bitPosi);
			/* single or double only applies when sense is 0(edge trigger). */
			if ( single == 0 )
				LPC_GPIO3->IBE &= ~(0x1<<bitPosi);
			else
				LPC_GPIO3->IBE |= (0x1<<bitPosi);
		}
		else
			LPC_GPIO3->IS |= (0x1<<bitPosi);

		if ( event == 0 )
			LPC_GPIO3->IEV &= ~(0x1<<bitPosi);
		else
			LPC_GPIO3->IEV |= (0x1<<bitPosi);		
	break;
	default:
		break;
	}
	return;
}

/*****************************************************************************
** Function name:		GPIOIntEnable
**
** Descriptions:		Enable Interrupt Mask for a port pin.
**
** parameters:			port num, bit position
** Returned value:		None
** 
*****************************************************************************/
void GPIOIntEnable( uint32_t portNum, uint32_t bitPosi )
{
	switch ( portNum )
	{
	case PORT0:
		LPC_GPIO0->IE |= (0x1<<bitPosi); 
	break;
 	case PORT1:
		LPC_GPIO1->IE |= (0x1<<bitPosi);	
	break;
	case PORT2:
		LPC_GPIO2->IE |= (0x1<<bitPosi);			
	break;
	case PORT3:
		LPC_GPIO3->IE |= (0x1<<bitPosi);			
	break;
	default:
		break;
	}
	return;
}

/*****************************************************************************
** Function name:		GPIOIntDisable
**
** Descriptions:		Disable Interrupt Mask for a port pin.
**
** parameters:			port num, bit position
** Returned value:		None
** 
*****************************************************************************/
void GPIOIntDisable( uint32_t portNum, uint32_t bitPosi )
{
	switch ( portNum )
	{
	case PORT0:
		LPC_GPIO0->IE &= ~(0x1<<bitPosi); 
	break;
 	case PORT1:
		LPC_GPIO1->IE &= ~(0x1<<bitPosi);	
	break;
	case PORT2:
		LPC_GPIO2->IE &= ~(0x1<<bitPosi);			
	break;
	case PORT3:
		LPC_GPIO3->IE &= ~(0x1<<bitPosi);			
	break;
	default:
		break;
	}
	return;
}

/*****************************************************************************
** Function name:		GPIOIntStatus
**
** Descriptions:		Get Interrupt status for a port pin.
**
** parameters:			port num, bit position
** Returned value:		None
** 
*****************************************************************************/
uint32_t GPIOIntStatus( uint32_t portNum, uint32_t bitPosi )
{
	uint32_t regVal = 0;

	switch ( portNum )
	{
	case PORT0:
		if ( LPC_GPIO0->MIS & (0x1<<bitPosi) )
		regVal = 1;
	break;
 	case PORT1:
		if ( LPC_GPIO1->MIS & (0x1<<bitPosi) )
		regVal = 1;	
	break;
	case PORT2:
		if ( LPC_GPIO2->MIS & (0x1<<bitPosi) )
		regVal = 1;				
	break;
	case PORT3:
		if ( LPC_GPIO3->MIS & (0x1<<bitPosi) )
		regVal = 1;				
	break;
	default:
		break;
	}
	return ( regVal );
}

/*****************************************************************************
** Function name:		GPIOIntClear
**
** Descriptions:		Clear Interrupt for a port pin.
**
** parameters:			port num, bit position
** Returned value:		None
** 
*****************************************************************************/
void GPIOIntClear( uint32_t portNum, uint32_t bitPosi )
{
	switch ( portNum )
	{
	case PORT0:
		LPC_GPIO0->IC |= (0x1<<bitPosi); 
	break;
 	case PORT1:
		LPC_GPIO1->IC |= (0x1<<bitPosi);	
	break;
	case PORT2:
		LPC_GPIO2->IC |= (0x1<<bitPosi);			
	break;
	case PORT3:
		LPC_GPIO3->IC |= (0x1<<bitPosi);			
	break;
	default:
		break;
	}
	return;
}

/*****************************************************************************
** Function name:		GPIOGetValue
**
** Descriptions:		Get a bitvalue in a specific bit position
**						in GPIO portX(X is the port number.)
**
** parameters:			port num, bit position
** Returned value:		None
**
*****************************************************************************/
uint32_t GPIOGetValue( uint32_t portNum, uint32_t bitPosi )
{
	return LPC_GPIO[portNum]->MASKED_ACCESS[(1<<bitPosi)];
	//return outpw(0,0);
}

/*****************************************************************************
** Function name:		GPIOSetValue
**
** Descriptions:		Set/clear a bitvalue in a specific bit position
**						in GPIO portX(X is the port number.)
**
** parameters:			port num, bit position, bit value
** Returned value:		None
**
*****************************************************************************/
void GPIOSetValue( uint32_t portNum, uint32_t bitPosi, uint32_t bitVal )
{
	LPC_GPIO[portNum]->MASKED_ACCESS[(1<<bitPosi)] = (bitVal<<bitPosi);
}
/*****************************************************************************
** Function name:		GPIOSetDir
**
** Descriptions:		Set the direction in GPIO port
**
** parameters:			port num, bit position, direction (1 out, 0 input)
** Returned value:		None
**
*****************************************************************************/
void GPIOSetDir( uint32_t portNum, uint32_t bitPosi, uint32_t dir )
{
	if(dir)
		LPC_GPIO[portNum]->DIR |= 1<<bitPosi;
	else
		LPC_GPIO[portNum]->DIR &= ~(1<<bitPosi);
}

// Define interface
// Make it high
void DrvGPIO_SetBit( uint32_t portNum, uint32_t bitPosi )
{
	// Make out put
	//GPIOSetDir(	portNum, bitPosi ,E_IO_OUTPUT);
	// Set value
	GPIOSetValue( portNum, bitPosi,1);

}
// Make it low
void DrvGPIO_ClrBit( uint32_t portNum, uint32_t bitPosi )
{
	// Make out put
	//GPIOSetDir(	portNum, bitPosi ,E_IO_OUTPUT);
	// Set value
	GPIOSetValue( portNum, bitPosi,0);

}
// Get value
uint32_t DrvGPIO_GetBit( uint32_t portNum, uint32_t bitPosi )
{
	// Set value
	return GPIOGetValue( portNum, bitPosi);

}
void DrvGPIO_Open( uint32_t portNum, uint32_t bitPosi, uint32_t dir )
{
	 
	 if (dir== E_IO_OUTPUT)	//1
	 {
	 	
		if ((LPC_GPIO[portNum]->DIR & (1<<bitPosi)) ==0) // current input
		{
			if (GPIOGetValue(portNum,bitPosi)==0)	// low
			{
				GPIOSetValue( portNum, bitPosi,0);	
			}
			else	 
			{
				GPIOSetValue( portNum, bitPosi,1); // high
			}
		}
		
	 }
	 GPIOSetDir(portNum,bitPosi,dir);
	 
}



/******************************************************************************
**														End Of File
******************************************************************************/
